﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml.Linq;

namespace MonoCompatibleChineseSegmenter
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.Error.WriteLine("Missing argument FILENAME");
                Console.Error.WriteLine("Usage : cseg.exe <FILENAME> [<OUTFILE>] [/simp | /trad] [/xx] [/nolicence]");
                Console.Error.WriteLine("Use /simp switch to parse simplified chinese.");
                Console.Error.WriteLine("Specifie the separator in output as a decimal ASCII value (default is \n).");
                Environment.Exit(1);
            }

            if(args.Length > 4)
                Console.WriteLine("The binary includes data extracted from http://www.chine-informations.com/chinois/open/CFDICT/");

            bool trad = true;
            char separator = '\n';

            if (args.Length > 2)
            {
                if (args[2].Equals("/simp"))
                {
                    trad = false;
                }
            }

            // gestion du séparateur

            if (args.Length > 3)
            {
                int intSep = 10;
                Int32.TryParse(args[3].Replace("/", ""), out intSep);
                separator = (char)intSep;
            }

            string fileContent = "";

            if (File.Exists(args[0]))
            {
                try
                {
                    using (StreamReader sr = new StreamReader(args[0]))
                    {
                        fileContent = sr.ReadToEnd();
                    }
                }
                catch (Exception)
                {
                    Console.Error.WriteLine(String.Format("Error while reading the file [{0}].", args[0]));
                }
            }
            else
            {
                Console.Error.WriteLine(String.Format("File [{0}] doesn't exists.", args[0]));
            }

            string parseResult;
            // open and read file

            if (trad)
            {
                parseResult = ParseTraditional(fileContent, separator);
            }
            else
            {
                parseResult = ParseSimplified(fileContent, separator);
            }

            if (args.Length > 1)
            {
                try
                {
                    using (StreamWriter sr = new StreamWriter(args[1]))
                    {
                        sr.Write(parseResult);
                    }
                }
                catch (Exception)
                {
                    Console.Error.WriteLine(String.Format("Error while writing the output file [{0}].", args[1]));
                }
            }
            else
            {
                Console.WriteLine(parseResult);
            }
            int i = 0;
        }

        private static string ParseTraditional(string text, char separator)
        {
            return Convert(text, "traditional", separator);
        }

        private static string ParseSimplified(string text, char separator)
        {
            return Convert(text, "simplified", separator);
        }

        private static string Convert(string sourceText, string scriptType, char separator)
        {
            XDocument xdoc;
            var assembly = Assembly.GetExecutingAssembly();
            var resourceName = "MonoCompatibleChineseSegmenter.minidic.xml";

            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    xdoc = XDocument.Load(reader);
                }
            }

            int position_pointer = 0;
            int segment_size = 4;
            string temp_segment = "";
            StringBuilder resultText = new StringBuilder();
            XElement xtmp;

            // boucle dont la condition d'arrêt doit prendre en compte la taille du segment (doit être supérieure à 0)
            // ainsi que la taille du texte : il ne faut pas que position_pointer + segment_size > sourceText.Length

            while (position_pointer < sourceText.Length)
            {
            // faire un filtre avant de s'attaquer au segment en cours pour vérifier si le 
            // prochain character est bien un kanji
            exit:
                segment_size = 4;

                for (int i = segment_size; i > 0; i--, segment_size--)
                {
                    while (position_pointer + segment_size > sourceText.Length)
                    {
                        segment_size--;
                        if (segment_size == 0)
                            return resultText.ToString();
                    }
                    temp_segment = sourceText.Substring(position_pointer, segment_size);
                    // cherche dans le dico
                    var query = from word in xdoc.Element("dic").Elements()
                                where word.Element(scriptType).Value.ToString() == temp_segment
                                select word;

                    if (query.ToArray().GetLength(0) > 0)
                    {
                        xtmp = query.ToArray()[0];
                        //resultText.AppendFormat("{0}\t{1}\n",
                        //    xtmp.Element("traditional").Value.ToString(),
                        //    PinyinFormatCorrection(xtmp.Element("pinyin").Value.ToString()));

                        foreach (XElement elem in xtmp.Elements("translations"))
                        {
                        //    resultText.AppendFormat("{0}\n",
                        //        TranslationFormatCorrection(elem.Element("translation").Value.ToString()));
                        }

                        resultText.Append(xtmp.Element(scriptType).Value.ToString());

                        resultText.Append(separator);

                        position_pointer += segment_size;
                        goto exit;
                    }
                    if (segment_size == 1)
                    {
                        position_pointer++;
                        goto exit;
                    }
                }
            }

            return resultText.ToString();
        }


    }
}
